#include "deepseek_server.h"
#include <iostream>
#include <sstream>

#include "conf.h"

std::string DeepseekServer::willingBuffer = "";
std::string DeepseekServer::buffer = "";
bool DeepseekServer::isResponse = false;
bool DeepseekServer::is_post_done = true;

std::function<void(const std::string&)> DeepseekServer::user_stream_callback = nullptr;
std::function<void(const std::string&)> DeepseekServer::user_callback = nullptr;

using json = nlohmann::json;


size_t DeepseekServer::writeCallback(void* ptr, size_t size, size_t nmemb, void* userp) {
    
    DeepseekServer* self = static_cast<DeepseekServer*>(userp);

    // 接收到的数据
    std::string data(static_cast<char*>(ptr), size * nmemb);

    // 解析数据
    self->parseResponse(data);

    return size * nmemb;
}

bool DeepseekServer::postRequest(const std::string& question) {
    if (!curl)    return false;

    // temperature 设置为0.15会更加的循规蹈矩

    std::string postData = R"({
        "model": "deepseek-r1:32b",
        "stream": true,
        "keep_alive": -1,
        "format": {
            "properties": {
            "robot_message_to_patient": {"type": "string"}
            },
            "required": ["robot_message_to_patient"]
        },
        "options": {
            "temperature": 0.15,
            "top_p": 0.85,
            "max_tokens": 30
        },
        "messages": [
            {
                "role": "user",
                "content": ")" + question + R"("
            }
        ]
    })";

    sys_log("%s", postData.c_str());

    // 设置 POST 数据
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());

    // 设置写回调函数
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    // 设置回调函数参数
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);

    // 发送请求
    is_post_done = false;
    isResponse = false;
    CURLcode res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        return false;
    }

    return true;
}



size_t DeepseekServer::willingWriteCallback
(void* ptr, size_t size, size_t nmemb, void* userp) {
    
    DeepseekServer* self = static_cast<DeepseekServer*>(userp);

    // 接收到的数据
    std::string data(static_cast<char*>(ptr), size * nmemb);

    willingBuffer += data;

    // 解析数据
    self->parseResponse(data);

    return size * nmemb;
}


void DeepseekServer::willingAddToBuffer(const std::string& content) {
    // 将内容追加到缓冲区
    buffer += content;

    // 前缀一定是 "{ "response": "，长度为 14
    const std::string prefix = "{ \"robot_message_to_patient\": \"";
    const size_t prefixLength = prefix.length();

    if (isResponse) {
        // 查找结束符 ", "is_patient_wants
        sys_log("buffer: %s", buffer.c_str());

        size_t endPos = buffer.find("\", \"is_patient_wants");

        // 找到了结束符
        if (endPos != std::string::npos) {

            // 删掉 "\" }" 及其后面的所有字符
            buffer.erase(endPos);

            is_post_done = true;

            // 调用用户设置的回调函数
            sys_log("%s -> user_callback", __func__);
            if (user_callback) user_callback(buffer);

            // 清空 buffer
            buffer.clear();
        }
        // 没有找到结束符
        else {
            if (user_stream_callback) user_stream_callback(content);
        }
    }

    // 第一次遇到大于 prefix.length() 的时候
    // 删除前面 prefix.length() 的字符，表示解析到了 response
    if (!isResponse && buffer.size() >= prefixLength) {
        isResponse = true;

        // 将 buffer 前面的 prefix.length() 数据抹除掉，剩下的调用流式回调
        buffer.erase(0, prefixLength);
        if (!buffer.empty() && user_stream_callback) {
            user_stream_callback(buffer);
        }
    }
}


void DeepseekServer::willingParseResponse(const std::string& response) {
    if (response.empty())  return;

    sys_log("res: %s", response.c_str());

    try {
        // 解析 JSON
        json jsonResponse = json::parse(response);

        // 检查是否包含 "message" 字段
        if (jsonResponse.contains("message") && 
            jsonResponse["message"].contains("content")) {

            // 从 json 中解析出 content 字段
            std::string content = jsonResponse["message"]["content"];

            // buffer 负责处理 content 字段中负责语音播放的内容
            if (!is_post_done) {
                addToBuffer(content);
            }

        }

        // 检查请求是否完成(如果找不到结束符\" }，这个可以作为保险，保证响应一定结束)
        if (jsonResponse.contains("done") && jsonResponse["done"] == true) {

            // 改变已经完成 post 请求的标志
            is_post_done = true;

            // 调用 用户设置的回调函数
            sys_log("%s -> user_callback", __func__);
            if (user_callback) {
                user_callback(buffer);
            }

            // 清空 buffer
            buffer.clear();
        }

    } catch (const json::parse_error& e) {
        std::cerr << "JSON parse error: " << e.what() << std::endl;
    }
}

bool DeepseekServer::checkPatientWillingToCotinue(const std::string& question) {
    if (!curl)    return false;

    std::string postData = R"({
        "model": "deepseek-r1:32b",
        "stream": true,
        "keep_alive": -1,
        "format": {
            "properties": {
            "robot_message_to_patient": {"type": "string"},
            "is_patient_wants_to_continue_talking_with_robot": {"type": "boolean"}
            },
            "required": ["robot_message_to_patient", "is_patient_wants_to_continue_talking_with_robot"]
        },
        "options": {
            "temperature": 0.1,
            "top_p": 0.85,
            "max_tokens": 100
        },
        "messages": [
            {
                "role": "user",
                "content": "你是一名在医院陪伴患者聊天的机器人，你刚刚询问患者是否有问题想要询问你，这是患者对你说的话：“)" 
                + question + 
                R"(”，请对患者进行回复，并判断患者是否想要继续和机器人聊天。不要输出英文字符。"
                "如果患者想要继续聊天的话，你需要在最后询问患者是否有其他问题想要询问。"
                "如果患者不想要继续聊天的话，你应该祝福患者，不要抛出问题。"
            }
        ]
    })";

    // sys_log("%s", postData.c_str());

    // 设置 POST 数据
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());

    // 设置写回调函数
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, willingWriteCallback);
    // 设置回调函数参数
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);

    // 发送请求
    is_post_done = false;
    isResponse = false;
    CURLcode res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        return false;
    }

    // 解析全部的 json，来判断患者是否愿意继续对话

    // sys_log("willing buffer: %s", willingBuffer.c_str());


    willingBuffer.clear();

    return true;
}


void DeepseekServer::addToBuffer(const std::string& content) {
    // 将内容追加到缓冲区
    buffer += content;

    // 前缀一定是 "{ "response": "，长度为 14
    const std::string prefix = "{ \"robot_message_to_patient\": \"";
    const size_t prefixLength = prefix.length();

    if (isResponse) {
        // 查找结束符 "\" }"
        size_t endPos = buffer.find("\" }");

        // 找到了结束符
        if (endPos != std::string::npos) {

            // 删掉 "\" }" 及其后面的所有字符
            buffer.erase(endPos);

            is_post_done = true;

            // // 调用用户设置的回调函数
            // sys_log("%s -> user_callback", __func__);
            // if (user_callback) user_callback(buffer);

            // 清空 buffer
            buffer.clear();
        }
        // 没有找到结束符
        else {
            if (user_stream_callback) user_stream_callback(content);
        }
    }

    // 第一次遇到大于 prefix.length() 的时候
    // 删除前面 prefix.length() 的字符，表示解析到了 response
    if (!isResponse && buffer.size() >= prefixLength) {
        isResponse = true;

        // 将 buffer 前面的 prefix.length() 数据抹除掉，剩下的调用流式回调
        buffer.erase(0, prefixLength);
        if (!buffer.empty() && user_stream_callback) {
            user_stream_callback(buffer);
        }
    }
}



void DeepseekServer::parseResponse(const std::string& response) {
    if (response.empty())  return;

    try {
        // 解析 JSON
        json jsonResponse = json::parse(response);

        // 检查是否包含 "message" 字段
        if (jsonResponse.contains("message") && 
            jsonResponse["message"].contains("content")) {

            // 从 json 中解析出 content 字段
            std::string content = jsonResponse["message"]["content"];

            // buffer 负责处理 content 字段中负责语音播放的内容
            if (!is_post_done) {
                addToBuffer(content);
            }

        }

        // 检查请求是否完成(如果找不到结束符\" }，这个可以作为保险，保证响应一定结束)
        if (jsonResponse.contains("done") && jsonResponse["done"] == true) {

            // 调用 用户设置的回调函数，如果 is_post_done = true 說明之前調用過 user_callback
            sys_log("%s -> user_callback", __func__);
            // if (user_callback && !is_post_done) {
            //     user_callback(buffer);
            // }
            if (user_callback) {
                user_callback(buffer);
            }

            // 改变已经完成 post 请求的标志
            is_post_done = true;

            // 清空 buffer
            buffer.clear();
        }

    } catch (const json::parse_error& e) {
        std::cerr << "JSON parse error: " << e.what() << std::endl;
    }
}


size_t DeepseekServer::check_writeCallback(void* ptr, size_t size, size_t nmemb, void* userp) {
    // 将响应数据追加到字符串中
    ((std::string*)userp)->append((char*)ptr, size * nmemb);
    return size * nmemb;
}

bool DeepseekServer::check_patient_ready_to_go_back(const std::string& question, std::string & llmRet)
{
    if (!curl) {
        sys_log("Failed to initialize CURL.");
        return false;
    }

    // 构造 POST 数据
    std::string postData = R"({
        "model": "deepseek-r1:32b",
        "stream": false,
        "keep_alive": -1,
        "format": {
            "properties": {
                "reason": {"type": "string"},
                "is_patient_finished_checkup_and_ready_to_go_back": {"type": "boolean"}
            },
            "required": ["reason", "is_patient_finished_checkup_and_ready_to_go_back"]
        },
        "options": {
            "temperature": 0.1,
            "top_p": 0.85,
            "max_tokens": 100
        },
        "messages": [
            {
                "role": "user",
                "content": "你是一名在医院帮助患者回到病房的机器人，这是患者对你说的话：“)" + question + R"(”，请判断患者是否已经体检完毕并想要回到病房。"
            }
        ]
    })";

    // 设置 POST 数据
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());

    std::string responseData;

    // 设置 curl 的回调函数
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, check_writeCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);

    sys_log("check_patient_ready_to_go_back send request.");

    // 发送请求：
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        return false;
    }

    sys_log("check_patient_ready_to_go_back done.");

    // 解析响应
    std::string reason;    // deepseek给出的isReady的理由
    bool isReady = false;  // 病人是否准备回到病房
    try {
        // 解析 JSON 字符串
        json jsonData = json::parse(responseData);

        // 提取 message.content 字段
        std::string content = jsonData["message"]["content"];

        // 将 content 解析为嵌套的 JSON 对象
        json nestedJson = json::parse(content);

        // 提取 reason 和 is_patient_finished_checkup_and_ready_to_go_back 字段
        reason = nestedJson["reason"];
        isReady = nestedJson["is_patient_finished_checkup_and_ready_to_go_back"];
    } catch (const std::exception& e) {
        // 捕获并处理 JSON 解析错误
        std::cerr << "JSON parsing error: " << e.what() << std::endl;
        return false;
    }

    sys_log("is_patient_finished_checkup_and_ready_to_go_back: %s\n"
            "deepseek reason: %s", isReady ? "true":"false", reason.c_str());

    llmRet = reason;

    return isReady;
}
